package com.abo.yaas.view.widgets.forms;

import org.vaadin.autoreplacefield.EuroField;
import org.vaadin.dialogs.ConfirmDialog;
import org.vaadin.hene.expandingtextarea.ExpandingTextArea;

import com.abo.yaas.AuctionResolverServlet;
import com.abo.yaas.domain.Auction;
import com.abo.yaas.i18n.TranslationUtil;
import com.abo.yaas.utils.EmailUtils;
import com.abo.yaas.view.ViewHandler;
import com.abo.yaas.view.widgets.CommunicationExceptionNotification;
import com.abo.yaas.view.widgets.LocaleSensitiveButton;
import com.abo.yaas.view.widgets.fields.CategoryCombo;
import com.abo.yaas.view.widgets.fields.CustomTextField;
import com.abo.yaas.view.widgets.fields.UploadImageField;
import com.abo.yaas.view.widgets.panels.AuctionTablePanel;
import com.abo.yaas.view.widgets.validators.DateValidator;
import com.abo.yaas.webservice.ResourceProvider;
import com.abo.yaas.webservice.exceptions.CommunicationException;
import com.vaadin.data.Item;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.validator.NullValidator;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.DateField;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.TextField;

@SuppressWarnings("serial")
public class AuctionForm extends Form implements Button.ClickListener {
    private static class AuctionFormFieldFactory extends DefaultFieldFactory {
        @Override
        public Field createField(Item item, Object propertyId, Component uiContext) {
            Field result = null;
            if ("preview".equals(propertyId)) {
                result = new UploadImageField(uiContext.getApplication());
                result.addValidator(new NullValidator("Please load Preview!", false));
            }
            if ("title".equals(propertyId)) {
                result = new CustomTextField();
                result.addValidator(new NullValidator("You must specify the title!", false));
            }
            if ("startPrice".equals(propertyId)) {
                result = new EuroField();
                result.setWidth("100%");
                result.addValidator(new NullValidator("Please specify the start price!", false));
            }

            if ("minimumBid".equals(propertyId)) {
                result = new EuroField();
                result.setWidth("100%");
                result.addValidator(new NullValidator("Please specify the minimum bid!", false));
            }

            if ("endTime".equals(propertyId)) {
                result = new DateField();
                result.setWidth("100%");
                result.setInvalidAllowed(true);
                ((DateField) result).setImmediate(true);
                ((DateField) result).setWriteThrough(true);
                ((DateField) result).setDateFormat("dd-MM HH:mm");
                ((DateField) result).setResolution(DateField.RESOLUTION_HOUR);
                result.addValidator(new NullValidator("Please specify the end date!", false));
                result.addValidator(new DateValidator("The period of the auction is too short"));
            }

            if ("category".equals(propertyId) && item.getItemProperty("category").getValue() == null) {
                result = new CategoryCombo();
            }

            if ("description".equals(propertyId)) {
                result = new ExpandingTextArea();
                ((TextField) result).setNullRepresentation("");
                result.setWidth("100%");
                result.addValidator(new NullValidator("Description is required!", false));
            }

            if (!uiContext.isReadOnly() && result != null) {
                result.setRequired(true);
            }
            if (result != null) {
                result.setCaption(TranslationUtil.getFieldTranslation(Auction.class, (String) propertyId));
            }
            return result;
        }
    }

    private final GridLayout layout = new GridLayout(2, 16);

    public AuctionForm() {
        super();
        layout.setSizeUndefined();
        layout.setSpacing(true);
        layout.setWidth("100%");
        setLayout(layout);
        setImmediate(true);
        setWriteThrough(false);
        setFormFieldFactory(new AuctionFormFieldFactory());
        setupFooter();
    }

    @Override
    protected void attachField(Object propertyId, Field field) {
        if (propertyId.equals("preview")) {
            layout.addComponent(field, 0, 0, 0, 6);
            return;
        }
        if (propertyId.equals("title")) {
            layout.addComponent(field, 1, 0);
            return;
        }
        if (propertyId.equals("startPrice")) {
            layout.addComponent(field, 1, 1);
            return;
        }
        if (propertyId.equals("minimumBid")) {
            layout.addComponent(field, 1, 2);
            return;
        }

        if (propertyId.equals("endTime")) {
            layout.addComponent(field, 1, 3);
            return;
        }
        if (propertyId.equals("category")) {
            layout.addComponent(field, 1, 4);
            return;
        }
        if (propertyId.equals("description")) {
            layout.addComponent(field, 0, 7, 1, 15);
            return;
        }
    }

    @Override
    public void buttonClick(ClickEvent event) {
    }

    public void cancel() {
        discard();
        ViewHandler.activateView(AuctionTablePanel.class);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void commit() throws SourceException, InvalidValueException {
        super.commit();
        Auction entity = ((BeanItem<Auction>) getItemDataSource()).getBean();
        if (entity != null) {
            try {
                entity = ResourceProvider.getEntityProvider(Auction.class).saveEntity(entity);
                AuctionResolverServlet.addAuctionTask(entity);
            } catch (final CommunicationException e) {
                getWindow().showNotification(new CommunicationExceptionNotification(e));
            }
        }
    }

    private void setupFooter() {
        final Button okButton = new LocaleSensitiveButton("OK_BUTTON", this, "submit");
        final Button cancelButton = new LocaleSensitiveButton("CANCEL_BUTTON", this, "cancel");
        final HorizontalLayout footer = new HorizontalLayout();
        footer.setSizeUndefined();
        footer.setMargin(true);
        footer.setSpacing(true);
        footer.addComponent(okButton);
        footer.addComponent(cancelButton);
        setFooter(footer);
    }

    public void submit() {
        if (!isReadOnly()) {
            try {
                ConfirmDialog.show(getWindow(), "Are You sure you want to create the auction",
                        new ConfirmDialog.Listener() {
                            @SuppressWarnings("unchecked")
                            @Override
                            public void onClose(ConfirmDialog dialog) {
                                if (dialog.isConfirmed()) {
                                    commit();
                                    try {
                                        EmailUtils.sendAuctionCreatedEmail(((BeanItem<Auction>) getItemDataSource())
                                                .getBean());
                                        ViewHandler.activateView(AuctionTablePanel.class);
                                    } catch (final Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        });
            } catch (final Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }

}
